;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Brett Kelly's .emacs
;; http://brettkelly.org
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; User Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(setq user-email-address "brett@brettkelly.org")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; First Things First
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Load Path
(setq load-path (append load-path (list "~/elisp/")))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Interface stuff
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(global-font-lock-mode 1)
(setq font-lock-maximum-decoration t)
(show-paren-mode t)
(transient-mark-mode t)
(autoload 'mwheel-install "mwheel" "Enable Mouse Wheel." t)
(blink-cursor-mode nil)
(turn-on-auto-fill)
(set-fill-column 78)
(setq default-tab-width 4)
(setq-default indent-tabs-mode nil)
(setq tab-width 4)
(line-number-mode 1)
(column-number-mode 1)
(display-time)
(setq inhibit-startup-message t)
(require 'color-theme)
(color-theme-resolve)
(mouse-avoidance-mode 'exile)
(setq require-final-newline t)
;; Turn off all this GUI action
(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(if (fboundp 'menu-bar-mode) (menu-bar-mode -1))
(setq tooltip-mode nil)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Kill-Ring
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'browse-kill-ring)
(browse-kill-ring-default-keybindings)
(global-set-key (kbd "C-c r") 'browse-kill-ring)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Dired
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'dired-x)
;; Let me delete non-empty directories in Dired
(setq dired-recursive-deletes 'always)
(setq dired-recursive-copies 'top)

;; Stolen from resolve/#emacs
(defun sof/dired-sort ()
  "Dired sort hook to list directories first."
  (save-excursion
   (let (buffer-read-only)
     (forward-line 2) ;; beyond dir. header
     (sort-regexp-fields t "^.*$" "[ ]*." (point) (point-max))))
  (set-buffer-modified-p nil))
(add-hook 'dired-after-readin-hook 'sof/dired-sort)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;  IswitchBuffers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(iswitchb-mode 1)
(add-to-list 'iswitchb-buffer-ignore
             "\\*\\(Group\\|Completions\\|Help\\)\\*")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Default Hooks and Behaviors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(setq default-major-mode 'text-mode)
(add-hook 'text-mode-hook 'text-mode-hook-identify)
(add-hook 'text-mode-hook 'turn-on-auto-fill)

;; Delete recovery files (#file#) when emacs exits
(add-hook 'kill-emacs-hook
          '(lambda ()
             (mapcar (lambda (buf)
                       (with-current-buffer buf
                         (delete-auto-save-file-if-necessary t)))
                     (buffer-list))))

;; Put all backup files in one spot
(add-to-list 'backup-directory-alist '(".*" . "~/emacs-backup"))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Mode-Generic Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; Tab completion for everybody! (everybody who wants it, that is)
(defun indent-or-complete ()
  "Complete if point is at end of a word, otherwise indent line."
  (interactive)
  (if (looking-at "\\>")
      (dabbrev-expand nil)
    (indent-for-tab-command)))

;; Insert Timestamp
(defun insert-timestamp ()
  (interactive)
  (insert comment-start " Edited by Brett Kelly - "
          (format-time-string "%c")))

;; Print a commented copy of the current line
(defun duplicate-and-comment-line ()
  (interactive)
  (save-excursion
    (let ((line (delete-and-extract-region (point-at-bol) (point-at-eol))))
      (insert comment-start line "\n" line))))



;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Keybindings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(global-set-key (kbd "C-m") 'newline-and-indent)
(global-set-key "\C-x\C-b" 'buffer-menu)
(global-set-key "\C-c\C-u" 'uncomment-region)
(global-set-key [f3] 'name-last-kbd-macro)
(global-set-key [f4] 'call-last-kbd-macro)
(global-set-key [f5] 'insert-kbd-macro)
(global-set-key "\C-x\C-k" 'kill-region)
(global-set-key "\C-cg" 'goto-line)
(global-set-key "\C-w" 'backward-kill-word)
(global-set-key "\C-cd" 'delete-blank-lines)
(global-set-key "\C-x\C-m" 'execute-extended-command)
(global-set-key "\C-c\C-m" 'execute-extended-command)
(global-set-key "\C-c\C-t" 'dabbrev-expand)
(global-set-key "\C-cj" 'join-line)
(global-set-key "\C-c\C-s" 'insert-timestamp)
(global-set-key "\C-c\C-d" 'duplicate-and-comment-line)
(global-set-key [f12] 'other-window)
(global-set-key [f11] 'apropos)
(global-set-key (kbd "S-C-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "S-C-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "S-C-<down>") 'shrink-window)
(global-set-key (kbd "S-C-<up>") 'enlarge-window)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Org-Mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; Write a function to mark a task done and move it to the end of the buffer

(require 'org)
(add-to-list 'auto-mode-alist '("\\.org$" . org-mode))
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(setq org-log-done t)

;; function to create a new todo list
(defun create-todo-list ()
  (interactive)
  (let* ((time (decode-time))
         (fname (format-time-string "~/org/%m%d%y.org"))
         (create-buffer (find-file fname)))
    (unless (file-exists-p fname)
      (insert (format-time-string "* Tasks: %m-%d-%y"))
      (insert "\n\n")
      (call-interactively 'org-insert-todo-heading))))
;; and bind it to C-c t globally
(global-set-key "\C-ct" 'create-todo-list)

;; extract the text of the current task
(defun org-get-current-task ()
  (let*
      ((terms "\\<\\(TODO\\|DONE\\|\\*\\)\\>")
       (start
        (progn
          (end-of-line)
          (re-search-backward terms)
          (beginning-of-line)
          (point)))
       (end
        (progn
          (next-line)
          (re-search-forward terms)
          (end-of-line 0)
          (point)))) 
    (and start end
         (delete-and-extract-region start end))))

;; remove current task and shove it at the end of the buffer
(defun org-insert-task-at-eob ()
  (interactive)
  (save-excursion)
  (let*
      ((p (point))
       (text (org-get-current-task)))
    (delete-blank-lines)
    (end-of-buffer)
    (unless (bolp)
      (insert "\n"))
    (delete-blank-lines)
    (insert text)
    (delete-blank-lines)
    (goto-char p)))
       
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Subversion
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'psvn)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Language-Specific Config
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Elisp
;;;;;;;;;;;;;;;;;;;;;;;;;
(add-hook 'emacs-lisp-mode
          (lambda ()
            (local-set-key "\C-c\C-c" 'comment-or-uncomment-region)
            (local-set-key (kbc "<tab>") 'indent-or-complete)))
(add-hook 'emacs-lisp-mode 'abbrev-mode)


;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Python
;;;;;;;;;;;;;;;;;;;;;;;;;
(autoload 'python-mode "python-mode" "Python editing mode." t)
(setq auto-mode-alist (cons '("\\.py$" . python-mode) auto-mode-alist))
(add-hook 'python-mode-hook 'abbrev-mode)
(add-hook 'python-mode-hook
           (lambda () (local-set-key (kbd "<tab>") 'indent-or-complete)))

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Perl
;;;;;;;;;;;;;;;;;;;;;;;;;
(defalias 'perl-mode 'cperl-mode)
(autoload 'perl-mode "perl-mode" "Perl Editing Mode." t)
(setq auto-mode-alist (cons '("\\.pl$" . perl-mode) auto-mode-alist))
(add-to-list 'interpreter-mode-alist '("perl" . cperl-mode))
(add-to-list 'interpreter-mode-alist '("perl5" . cperl-mode))
(add-to-list 'interpreter-mode-alist '("miniperl" . cperl-mode))
(defun n-cperl-mode-hook ()
  (setq cperl-indent-level 4)
  (setq cperl-continued-statement-offset 0)
  (setq cperl-extra-newline-before-brace t))
(add-hook 'cperl-mode-hook 'n-cperl-mode-hook t)
(add-hook 'cperl-mode-hook 'abbrev-mode)
(add-hook 'cperl-mode-hook
           (lambda () (local-set-key (kbd "<tab>") 'indent-or-complete)))

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; C#
;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'cc-mode)  ;; otherwise, csharp mode won't work
(autoload 'csharp-mode "csharp-mode" "C# Editing Mode." t)
(setq auto-mode-alist (cons '("\\.cs$" . csharp-mode) auto-mode-alist))
(add-hook 'csharp-mode-hook 'abbrev-mode)
(add-hook 'csharp-mode-hook
          (lambda ()
            (setq c-basic-offset 4)
            (load-file "~/elisp/cs-macros.el")
            (local-set-key (kbd "<tab>") 'indent-or-complete)
            (local-set-key "\C-c\C-r" 'comment-region)
            (local-set-key "\C-c\C-r" 'uncomment-region)))
            
;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; SQL
;;;;;;;;;;;;;;;;;;;;;;;;;
(autoload 'sql-mode "sql-mode" "SQL Editing Mode" t)
(setq auto-mode-alist (cons '("\\.sql$" . sql-mode) auto-mode-alist))

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; PHP
;;;;;;;;;;;;;;;;;;;;;;;;;
(autoload 'php-mode "php-mode" "PHP Editing Mode" t)
(setq auto-mode-alist (cons '("\\.php$" . php-mode) auto-mode-alist))
(add-hook 'php-mode 'abbrev-mode)

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; HTML
;;;;;;;;;;;;;;;;;;;;;;;;;
(autoload 'html-helper-mode "html-helper-mode" "HTML Editing Mode" t)
(setq auto-mode-alist (cons '("\\.html$" . html-helper-mode) auto-mode-alist))

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Javascript
;;;;;;;;;;;;;;;;;;;;;;;;;
(autoload 'javascript-mode "javascript-mode" "Javascript Editing Mode" t)
(setq auto-mode-alist (cons '("\\.js$" . javascript-mode) auto-mode-alist))

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; CSS
;;;;;;;;;;;;;;;;;;;;;;;;;
(autoload 'css-mode "css-mode" "CSS Editing Mode" t)
(setq auto-mode-alist (cons '("\\.css$" . css-mode) auto-mode-alist))

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Slime
;;;;;;;;;;;;;;;;;;;;;;;;;
(add-to-list 'load-path "~/elisp/slime-2.0")
(add-hook 'lisp-mode-hook (lambda () (slime-mode t)))
(setq inferior-lisp-program "C:/installers/clisp-2.39/clisp.exe")
(require 'slime)
(slime-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Cheetah
;;;;;;;;;;;;;;;;;;;;;;;;;

(define-derived-mode cheetah-mode html-mode "Cheetah"
  (make-face 'cheetah-variable-face)
  (font-lock-add-keywords
   nil
   '(
     ("\\(#\\(from\\|else\\|include\\|set\\|import\\|for\\|if\\|end\\)+\\)\\>" 1 font-lock-type-face)
     ("\\(#\\(from\\|for\\|end\\)\\).*\\<\\(for\\|import\\|if\\|in\\)\\>" 3 font-lock-type-face)
     ("\\(\\$\\(?:\\sw\\|}\\|{\\|\\s_\\)+\\)" 1 font-lock-variable-name-face))
   )
  (font-lock-mode 1)
  )
(setq auto-mode-alist (cons '( "\\.tmpl\\'" . cheetah-mode ) auto-mode-alist ))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Other Mode-Specific Config
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; rcirc
;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'rcirc)

; Tracker
(rcirc-track-minor-mode 1)

; Default settings
(setq rcirc-default-nick "inkedmn"
      rcirc-time-format "%R "
      rcirc-buffer-maximum-lines 1000
      rcirc-authinfo '(("oftc" nickserv "inkedmn" "yeah right")
                       ("freenode" nickserv "inkedmn" "yeah right"))
      rcirc-startup-channels-alist '(("oftc" "#grasshoppers")
                                     ("freenode" "#emacs" "#ma.gnolia")))

; Make my own nickname red
(set-face-foreground 'rcirc-my-nick "red" nil)

; Always keep the prompt at the bottom of the buffer
(add-hook 'rcirc-mode-hook
          '(lambda ()
             (set (make-local-variable 'scroll-conservatively) 8192)))

; Wrap long lines according to the width of the window
(add-hook 'window-configuration-change-hook
          '(lambda ()
             (setq rcirc-fill-column 78)))

(defun rcirc-kill-all-buffers ()
  (interactive)
  (kill-all-mode-buffers 'rcirc-mode))

(defun irc ()
  (interactive)
  (rcirc-connect "irc.oftc.net" 6667 rcirc-default-nick rcirc-default-nick rcirc-default-nick
                 (assoc "oftc" rcirc-startup-channels-alist))
  (rcirc-connect "irc.freenode.net" 6667 rcirc-default-nick rcirc-default-nick rcirc-default-nick
                 (assoc "freenode" rcirc-startup-channels-alist)))


;; Kill 'em all
(defun kill-all-irc-buffers ()
  "Loop through all buffers and kill RCIRC completely"
  (interactive)
  (when (y-or-n-p "Kill All RCIRC Buffers? ")
    (dolist (buf (buffer-list))
      (if (eq (with-current-buffer buf major-mode) 'rcirc-mode)
          (kill-buffer buf)))))
(global-set-key "\C-ck" 'kill-all-irc-buffers)

(defun irc-open-last-url-in-channel ()
  "Open Last Url Pasted in Browser"
  (interactive)
  (save-excursion
    (search-backward "http:")
    (browse-url-at-point)))
(global-set-key "\C-cu" 'irc-open-last-url-in-channel)
(add-hook 'rcirc-mode-hook
          '(lambda ()
             (local-set-key (kbd "\C-co") 'rcirc-open-last-url-in-channel)))

(defun get-last-urls (count)
  "Build a list of the <count> most recent urls in the buffer - Thanks Vince!"
  (let ((urls '())
        (n 0))
    (save-excursion
      (while
          (and (not (bobp))
               (< n count))
        (re-search-backward "\\(http://.*?\\)[,;:<>\n\s]" 0 t)
        (add-to-list 'urls (thing-at-point 'url))
        (incf n))
    urls)))

(defun handle-url-select ()
  (interactive)
  (goto-address-at-point)
  (local-set-key (kbd "RET") 'newline-and-indent)
  (bury-buffer)) 

(defun print-urls (count)
  "Exposed function to open list of urls and allow opening"
  (interactive)
  (save-excursion
   (let ((urls (get-last-urls count)))
     (switch-to-buffer "*urls*")
     (erase-buffer)
     (local-set-key (kbd "RET") 'handle-url-select)
     (dolist (url urls)
       (insert (url-normalize-url url) "\n"))
     (goto-char 1))))

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Aspell
;;;;;;;;;;;;;;;;;;;;;;;;;
(setq ispell-program-name "aspell")
(setq ispell-extra-args '("--sug-mode=ultra"))
(global-set-key "\C-cs" 'ispell-word)

;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; TRAMP
;;;;;;;;;;;;;;;;;;;;;;;;;
(add-to-list 'load-path "~/elisp/tramp/lisp")
(require 'tramp)
;(setq 'tramp-default-method "pscp")


; Sudoku!
(require 'sudoku)
(defvar sudoku-wget-process
  "C:\Program Files\Labrat Toolkit\UnxUtils\usr\local\wbin\wget.exe")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Auto-generated shiz - Don't edit below
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(custom-set-faces
  ;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
  ;; Your init file should contain only one such instance.
 )
